package top.shenluw.demo.querydsl;

import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.engine.jdbc.dialect.internal.StandardDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.type.IntegerType;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 重写 DialectResolver， 可以支持自己创建Dialect，这样就可以不继承不同数据库的Dialect
 * @author Shenluw
 * 创建日期：2018/9/29 15:18
 */
public class InjectSqlFunctionDialectResolver implements DialectResolver {

	public static final String SQL_FUNCTION_BITAND = "bitand";
	public static final String SQL_FUNCTION_BITOR  = "bitor";
	public static final String SQL_FUNCTION_BITXOR = "bitxor";

	private final static StandardDialectResolver RESOLVER = new StandardDialectResolver();

	@Override
	public Dialect resolveDialect(DialectResolutionInfo info) {
		Dialect dialect = RESOLVER.resolveDialect(info);
		Method  method  = ReflectionUtils.findMethod(dialect.getClass(), "registerFunction", String.class, SQLFunction.class);
		method.setAccessible(true);
		Map<String, SQLFunction> functions = dialect.getFunctions();
		if (!functions.containsKey(SQL_FUNCTION_BITAND)) {
			ReflectionUtils.invokeMethod(method, dialect, SQL_FUNCTION_BITAND, new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 & ?2)"));
		}
		if (!functions.containsKey(SQL_FUNCTION_BITOR)) {
			ReflectionUtils.invokeMethod(method, dialect, SQL_FUNCTION_BITOR, new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 | ?2)"));
		}
		if (!functions.containsKey(SQL_FUNCTION_BITXOR)) {
			ReflectionUtils.invokeMethod(method, dialect, SQL_FUNCTION_BITXOR, new SQLFunctionTemplate(IntegerType.INSTANCE, "(?1 ^ ?2)"));
		}
		return dialect;
	}
}
